package com.fjwt.gz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjwt.gz.core.constants.CS;
import com.fjwt.gz.core.constants.Constants;
import com.fjwt.gz.core.exception.BizException;
import com.fjwt.gz.db.entity.SysUser;
import com.fjwt.gz.db.entity.SysUserAuth;
import com.fjwt.gz.db.entity.SysUserRoleRela;
import com.fjwt.gz.service.mapper.SysUserMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 系统操作员表 服务实现类
 * </p>
 *
 * @author [mybatis plus generator]
 * @since 2020-06-13
 */
@Service
public class SysUserService extends ServiceImpl<SysUserMapper, SysUser> {

    @Autowired private SysUserAuthService sysUserAuthService;
    @Autowired private SysUserRoleRelaService sysUserRoleRelaService;
    @Autowired private SysConfigService sysConfigService;


    /** 添加系统用户 **/
    @Transactional
    public void addSysUser(SysUser sysUser, String sysType, String loginPassword){
        if( StringUtils.isEmpty(sysUser.getRealname()) ) {
            throw new BizException("姓名不能为空！");
        }
        if( StringUtils.isEmpty(sysUser.getTelphone()) ) {
            throw new BizException("手机号不能为空！");
        }
        if(sysUser.getSex() == null ) {
            throw new BizException("性别不能为空！");
        }

        //手机号不可重复
        if(count(SysUser.gw().eq(SysUser::getSysType, sysType).eq(SysUser::getTelphone, sysUser.getTelphone()).eq(SysUser::getBelongInfoId, sysUser.getBelongInfoId())) > 0 ){
            throw new BizException("手机号已存在！");
        }
        //超管用户不可重复
        if (com.fjwt.gz.core.entity.SysUser.UEST_TYPE_ADMIN == sysUser.getUserType()) {
            if (count(SysUser.gw()
                    .eq(SysUser::getUserType, com.fjwt.gz.core.entity.SysUser.UEST_TYPE_ADMIN)
                    .eq(SysUser::getBelongInfoId, sysUser.getBelongInfoId())) > 0) {
                throw new BizException("超管用户已存在！");
            }
        }

        //女  默认头像
        if(sysUser.getSex() != null && CS.SEX_FEMALE == sysUser.getSex()){
            sysUser.setAvatarUrl("https://jdyd-jhzf-public.oss-cn-hangzhou.aliyuncs.com/gz/img/defava_f.png");
        }else{
            sysUser.setAvatarUrl("https://jdyd-jhzf-public.oss-cn-hangzhou.aliyuncs.com/gz/img/defava_m.png");
        }


        resetSysUserPwdTime(sysUser, loginPassword);

        //1. 插入用户主表
        sysUser.setSysType(sysType); // 系统类型
        this.save(sysUser);

        Long sysUserId = sysUser.getSysUserId();

        sysUserAuthService.addUserAuthDefault(sysUserId, sysUser.getTelphone(), loginPassword, sysType);

    }

    // password为空，代表是默认密码
    public void resetSysUserPwdTime(SysUser sysUser, String password) {

        // 过期天数
        Integer expireDay = sysConfigService.getDBSecurityConfig().getPasswordExpireDay();
        if (StringUtils.isBlank(password) || expireDay == null) {
            expireDay = 0;
        }

        Date date = new Date();
        sysUser.setLastResetPwdTime(date);
        sysUser.setPwdExpiredTime(expireDay == 0 ? date : DateUtil.offsetDay(date, expireDay));

    }

    //修改用户信息
    // resetAuthInfo: 当更改操作员信息功能时需要更新  true
    // 重置商户信息，代理商信息时，不需要更新。 因为会与密码同时更新，避免多余的update操作。
    @Transactional
    public void updateSysUser(SysUser sysUser, boolean resetAuthInfo){

        Long sysUserId = sysUser.getSysUserId();
        SysUser dbRecord = getById(sysUserId);

        if (dbRecord == null) {
            throw new BizException("该用户不存在");
        }


        // 避免更新空串
        if(StringUtils.isEmpty(sysUser.getTelphone())){
            sysUser.setTelphone(null);
        }

        //修改了手机号， 需要修改auth表信息
        if(StringUtils.isNotEmpty(sysUser.getTelphone()) && !dbRecord.getTelphone().equals(sysUser.getTelphone())){

            if(count(SysUser.gw().eq(SysUser::getSysType, dbRecord.getSysType()).eq(SysUser::getTelphone, sysUser.getTelphone())) > 0){
                throw new BizException("该手机号已关联其他用户！");
            }

            if(resetAuthInfo){
                sysUserAuthService.resetAuthInfo(sysUserId, null, sysUser.getTelphone(), false, null, dbRecord.getSysType());
            }

        }


        //修改用户主表
        baseMapper.updateById(sysUser);
    }


    /** 分配用户角色 **/
    @Transactional
    public void saveUserRole(Long userId, List<String> roleIdList) {

        //删除用户之前的 角色信息
        sysUserRoleRelaService.remove(SysUserRoleRela.gw().eq(SysUserRoleRela::getUserId, userId));
        for (String roleId : roleIdList) {
            SysUserRoleRela addRecord = new SysUserRoleRela();
            addRecord.setUserId(userId); addRecord.setRoleId(roleId);
            sysUserRoleRelaService.save(addRecord);
        }
    }

    /** 删除用户 **/
    @Transactional
    public void removeUser(SysUser sysUser, String sysType) {
        // 1.删除用户登录信息
        sysUserAuthService.remove(SysUserAuth.gw()
                .in(SysUserAuth::getUserId, sysUser.getSysUserId())
        );
        // 2.删除用户角色信息
        sysUserRoleRelaService.remove(SysUserRoleRela.gw().eq(SysUserRoleRela::getUserId, sysUser.getSysUserId()));
        // 3.删除用户信息
        removeById(sysUser.getSysUserId());
    }


    /** 查询用户列表 **/
    public List<JSONObject> selectList(IPage iPage, SysUser queryObject) {

        Map<String, Object> params = genQueryParams(queryObject);
        params.put("limit", iPage.getSize());
        params.put("offset", iPage.offset());

        return baseMapper.selectUserPage(params);
    }

    /** 查询用户总数 **/
    public long queryCount(SysUser queryObject) {
        return baseMapper.selectUserCount(genQueryParams(queryObject));
    }

    public Map<String, Object> genQueryParams(SysUser queryObject) {

        Map<String, Object> params = new HashMap<>();

        if (StringUtils.isNotBlank(queryObject.getSysType())) {
            params.put("sysType", queryObject.getSysType());
        }
        if (StringUtils.isNotBlank(queryObject.getBelongInfoId())) {
            params.put("belongInfoId", queryObject.getBelongInfoId());
        }
        if (queryObject.getSysUserId() != null) {
            params.put("sysUserId", queryObject.getSysUserId());
        }
        if (StringUtils.isNotBlank(queryObject.getRealname())) {
            params.put("realname", queryObject.getRealname());
        }
        if (StringUtils.isNotBlank(queryObject.getTelphone())) {
            params.put("telphone", queryObject.getTelphone());
        }
        if (queryObject.getState() != null) {
            params.put("state", queryObject.getState());
        }
        if (queryObject.getUserType() != null) {
            params.put("userType", queryObject.getUserType());
        }
        if (CollUtil.isNotEmpty(queryObject.getAgentNoList())) {
            params.put("agentNoList", queryObject.getAgentNoList());
        }

        return params;
    }


    /** 重置密码,  如果 resetPassword = true && newPwd = null 那么使用的系统默认密码。   */
    @Transactional
    public void resetUserAndAuthInfo(Long resetUserId, String authLoginUserName, String telphone, boolean resetPassword, String newPwd, String sysType){

        // 有更新基础信息
        if(StringUtils.isNotEmpty(authLoginUserName) || StringUtils.isNotEmpty(telphone)){
            SysUser sysUser = new SysUser();
            sysUser.setSysUserId(resetUserId).setTelphone(telphone);
            this.updateSysUser(sysUser, false);
        }

        // 更新认证信息
        sysUserAuthService.resetAuthInfo(resetUserId, authLoginUserName, telphone, resetPassword, newPwd, sysType);

    }


    /** 更新上次登录时间 */
    public void updateLastLoginTime(Long sysUserId){

        if(sysUserId == null){
            return ;
        }

        SysUser updateRecord = new SysUser();
        updateRecord.setSysUserId(sysUserId);
        updateRecord.setLastLoginTime(new Date());
        updateById(updateRecord);
    }

}
